//
//  HybridWKWebView.swift
//  MeenoHybrid
//
//  Created by alyadan on 2016/10/15.
//  Copyright © 2016年 alyadan. All rights reserved.
//

import UIKit
import MVVM_BaseViewController
import YD_Util
import RxSwift
import JavaScriptCore

public class HybridWKWebView: WKWebView, WKNavigationDelegate {

    public override var currentModel: HybridWKWebViewModel? {
        
        return viewModel.value as? HybridWKWebViewModel
        
    }
    
    public convenience init(hybrdViewModel: HybridWKWebViewModel){
        
        self.init(frame: CGRect.zero, configuration: WKWebViewConfiguration(), hybrdViewModel: hybrdViewModel)
        
    }
    
    public init(frame: CGRect, configuration: WKWebViewConfiguration, hybrdViewModel: HybridWKWebViewModel) {
        
        super.init(frame: frame, configuration: configuration)
        
        self.viewModel.value = hybrdViewModel
        initView()
        
    }
    
    public required init?(coder: NSCoder) {
        
        super.init(coder: coder)
        
    }
    
    
    public override func setupUI() {
        
        self.backgroundColor = UIColor.clear
        self.isOpaque = false
        
        let mainBundle = Bundle.main.url(forResource: "WebViewJavascriptBridge", withExtension: "bundle")
        //特殊处理
        let mainHandler = MNWebViewMainHandler()
        //
        
        currentModel?.bridge = WKWebViewJavascriptBridge(for: self, webViewDelegate: self, handler: { (data, callback) in
            do{
               try mainHandler.deal(data: data, responseCallback: callback!)
                
            }catch{
               print(error)
            }
        }, resourceBundle: Bundle.init(url: mainBundle!))
        
        if let x = currentModel?.bridge{
            
            //特殊处理
            mainHandler.hybridVCModel = currentModel!.getHybridVCModel()
            //
            
            HybridHandlerCenter.share.register(bridge: x, webViewModel: currentModel!)
        }else{
            
            print("error: webBridge create failed!")
            
        }
        
        
        if let url = currentModel?.completeUrl{
            print(url.absoluteString)
            if MeenoHybrid.use_local_html {
                self.load(URLRequest.init(url: url))
            }else {
                let req = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 30)
                self.load(req)
            }
        }
        
    }
    
    
    public override func bindModelData() {
        
        let enterForeground = ["method":"appWillEnterForground", "data":[String:Any]()] as [String : Any]
        let enterBackground = ["method":"appDidEnterBackground", "data":[String:Any]()] as [String : Any]
       let sub1 = NotificationCenter.default.rx.notification(Notification.Name.UIApplicationWillEnterForeground).shareReplay(1)
       let sub2 = NotificationCenter.default.rx.notification(Notification.Name.UIApplicationDidEnterBackground).shareReplay(1)
        Observable.of(sub1, sub2).merge().bindNext {[unowned self] (x:Notification) in
            switch x.name {
            case Notification.Name.UIApplicationDidEnterBackground:
                
                self.currentModel?.bridge?.send(enterBackground)
//                self.currentModel?.bridge?.callHandler(data: enterBackground)
                
            case Notification.Name.UIApplicationWillEnterForeground:
                self.currentModel?.bridge?.send(enterForeground)
//                self.currentModel?.bridge?.callHandler(data: enterForeground)
            default:
                break
            }
        }.addDisposableTo(disposeBag)
        
    }
    
    //MARK: UIWebView
    public func webViewDidStartLoad(_ webView: UIWebView) {
        
       print("webView start load")
        
    }
    
    public func webViewDidFinishLoad(_ webView: UIWebView) {
        
       print("webView finish load")
        
    }
    
    //MARK:WKNavigationDelegate 
    /*
     public func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
     
     print("start webview")
     
     }
     
     public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
     
     print("finish webview")
     
     }
     
     */
    deinit {
        print("\(self) deinit")
    }
    
}

public class HybridBaseWebViewModel :MVVM_BaseViewModel {
    
    // like 
    // "loadding"
    // OR "loadding?param=p1&param2=p2 ..."
    public var htmlName:String
    
    let mainHandler = MNWebViewMainHandler()
    
    public weak var parentWebViewModel : HybridBaseWebViewModel?
    
    
    public var completeUrl : URL? {
        return jointUrl()
    }
    
    public var refreshType = Variable<Int>(3) // default is none 0 => up , 1 => down 2 => up | down
    public var isDownRefresh = Variable<Bool>(false)
    public var isUPRefresh = Variable<Bool>(false)
    public var isReloding = Variable<Bool>(false)
    public var dragable = Variable<Bool>(false)
    
    public init(parentViewModel: MVVM_BaseViewModel?, htmlName: String) {
        self.htmlName = htmlName
        super.init(parentViewModel: parentViewModel)
    }
    
    
    
    
    override public func setupModel() {
        if MeenoHybrid.enableLog {
            WKWebViewJavascriptBridge.enableLogging()
        }
    }
    
    
    func getHybridVCModel() -> HybridBaseVCModel {
        
        var parent: MVVM_BaseViewModel? = self
        
        while let x = parent?.parentViewModel  {
            
            if x.isKind(of: HybridBaseVCModel.self) {
                return x as! HybridBaseVCModel
            }
            
            parent = parent?.parentViewModel
            
        }
        
        assert(false, "WKWebView is not in a HybridBaseViewController")
        return HybridBaseVCModel(parentViewModel: nil)
    }
    
    
    //MARK: parse HTMLName
    func analysisHtmlName(htmlName: String) -> (namePart:String?, paramPart:String?) {
        let arr = htmlName.components(separatedBy: "?")
        
        func nameWithExtension(namePart: String) -> String {
            return namePart.hasSuffix(".html") ? arr[0] : arr[0] + ".html"
        }
        
        if arr.count > 1 {
            return (nameWithExtension(namePart: arr[0]), arr[1])
        }
        
        return (nameWithExtension(namePart: arr[0]), nil)
    }
    
    func jointUrl() -> URL? {
        guard htmlName != "" else {
            print("error : htmlName is empty")
            return nil
        }
        
        //namePart xxx.html
        let result = analysisHtmlName(htmlName: htmlName)
        
        
        
        if MeenoHybrid.use_local_html {
            guard "" != MeenoHybrid.local_path_name else {
                print("local_path_name is empty")
                return nil
            }
            
            guard let namePart = result.namePart else{
                print("wrong HtmlName")
                return nil
            }
            
            if let url = Bundle.main.url(forResource: namePart, withExtension: "", subdirectory: MeenoHybrid.local_path_name){
                let urlString = url.absoluteString + "?" + (result.paramPart ?? "")
                
                
                if let x = URL(string: urlString){
                   return x
                }else if let urlString = urlString.addingPercentEscapes(using: .utf8){
                    return URL(string: urlString)
                }
                
            }
            
            
        }else {
            guard "" != MeenoHybrid.remote_test_path else {
                print("local_path_name is empty")
                return nil
            }
            
            guard let namePart = result.namePart else{
                print("wrong HtmlName")
                return nil
            }
            
            let urlString = MeenoHybrid.remote_test_path + namePart + "?" + (result.paramPart ?? "")
            
            if let x = URL(string: urlString){
                return x
            }else if let urlString = urlString.addingPercentEscapes(using: .utf8){
                return URL(string: urlString)
            }
        }
            print("urlStrin to URL failed")
        
        return nil
    }
    
    
}

public class HybridWKWebViewModel: HybridBaseWebViewModel {
    
    public var bridge:WKWebViewJavascriptBridge?
    
    
}
